home *** CD-ROM | disk | FTP | other *** search
/ Shareware Overload Trio 2 / Shareware Overload Trio Volume 2 (Chestnut CD-ROM).ISO / dir24 / psi110g.zip / CMDPARSE.C < prev    next >
C/C++ Source or Header  |  1994-04-17  |  13KB  |  511 lines

  1. /* Parse command line, set up command arguments Unix-style, and call function.
  2.  * Note: argument is modified (delimiters are overwritten with nulls)
  3.  *
  4.  * Copyright 1991 Phil Karn, KA9Q
  5.  *
  6.  * Improved error handling by Brian Boesch of Stanford University
  7.  * Feb '91 - Bill Simpson
  8.  *              bit16cmd for PPP
  9.  * Mar '91 - Glenn McGregor
  10.  *              handle string escaped sequences
  11.  */
  12. #include <ctype.h>
  13. #ifdef MSDOS
  14. #include <conio.h>
  15. #endif
  16. #include "global.h"
  17. #include "proc.h"
  18. #include "cmdparse.h"
  19. #include "session.h"
  20. #include "pktdrvr.h"
  21. #include "iface.h"
  22. #include "socket.h"
  23.   
  24. struct boolcmd {
  25.     char *str;      /* Token */
  26.     int val;        /* Value */
  27. };
  28.   
  29. static struct boolcmd Boolcmds[] = {
  30.     "y",            1,      /* Synonyms for "true" */
  31.     "yes",          1,
  32.     "true",         1,
  33.     "on",           1,
  34.     "1",            1,
  35.     "set",          1,
  36.     "enable",       1,
  37.   
  38.     "n",            0,      /* Synonyms for "false" */
  39.     "no",           0,
  40.     "false",        0,
  41.     "off",          0,
  42.     "0",            0,
  43.     "clear",        0,
  44.     "disable",      0,
  45.     NULLCHAR
  46. };
  47.   
  48. static char *stringparse __ARGS((char *line));
  49.   
  50. static char *
  51. stringparse(line)
  52. char *line;
  53. {
  54.     register char *cp = line;
  55.     unsigned long num;
  56.   
  57.     while ( *line != '\0' && *line != '\"' ) {
  58.         if ( *line == '\\' ) {
  59.             line++;
  60.             switch ( *line++ ) {
  61.                 case 'n':
  62.                     *cp++ = '\n';
  63.                     break;
  64.                 case 't':
  65.                     *cp++ = '\t';
  66.                     break;
  67.                 case 'v':
  68.                     *cp++ = '\v';
  69.                     break;
  70.                 case 'b':
  71.                     *cp++ = '\b';
  72.                     break;
  73.                 case 'r':
  74.                     *cp++ = '\r';
  75.                     break;
  76.                 case 'f':
  77.                     *cp++ = '\f';
  78.                     break;
  79.                 case 'a':
  80.                     *cp++ = '\a';
  81.                     break;
  82.                 case '\\':
  83.                     *cp++ = '\\';
  84.                     break;
  85.                 case '\?':
  86.                     *cp++ = '\?';
  87.                     break;
  88.                 case '\'':
  89.                     *cp++ = '\'';
  90.                     break;
  91.                 case '\"':
  92.                     *cp++ = '\"';
  93.                     break;
  94.                 case 'x':
  95.                     num = strtoul( --line, &line, 16 );
  96.                     *cp++ = (char) num;
  97.                     break;
  98.                 case '0':
  99.                 case '1':
  100.                 case '2':
  101.                 case '3':
  102.                 case '4':
  103.                 case '5':
  104.                 case '6':
  105.                 case '7':
  106.                     num = strtoul( --line, &line, 8 );
  107.                     *cp++ = (char) num;
  108.                     break;
  109.                 case '\0':
  110.                     return NULLCHAR;
  111.                 default:
  112.                     *cp++ = *(line - 1);
  113.                     break;
  114.             };
  115.         } else {
  116.             *cp++ = *line++;
  117.         }
  118.     }
  119.   
  120.     if ( *line == '\"' )
  121.         line++;         /* skip final quote */
  122.     *cp = '\0';             /* terminate string */
  123.     return line;
  124. }
  125.   
  126. #ifdef LOCK
  127. int Kblocked;
  128. char *Kbpasswd;
  129. #endif
  130.   
  131. int
  132. cmdparse(cmds,line,p)
  133. struct cmds cmds[];
  134. register char *line;
  135. void *p;
  136. {
  137.     struct cmds *cmdp;
  138.     char *argv[NARG],*cp;
  139.     char **pargv;
  140.     int argc,i;
  141.   
  142.     /* Remove cr/lf */
  143.     rip(line);
  144.   
  145.     for(argc = 0;argc < NARG;argc++)
  146.         argv[argc] = NULLCHAR;
  147.   
  148.     for(argc = 0;argc < NARG;){
  149.         register int qflag = FALSE;
  150.   
  151.         /* Skip leading white space */
  152.         while(*line == ' ' || *line == '\t')
  153.             line++;
  154.         if(*line == '\0')
  155.             break;
  156.         /* return if comment character first non-white */
  157.         if ( argc == 0  &&  *line == '#' )
  158.             return 0;
  159.         /* Check for quoted token */
  160.         if(*line == '"'){
  161.             line++; /* Suppress quote */
  162.             qflag = TRUE;
  163.         }
  164.         argv[argc++] = line;    /* Beginning of token */
  165.   
  166.         if(qflag){
  167.             /* Find terminating delimiter */
  168.             if((line = stringparse(line)) == NULLCHAR){
  169.                 return -1;
  170.             }
  171.         } else {
  172.             /* Find space or tab. If not present,
  173.              * then we've already found the last
  174.              * token.
  175.              */
  176. #ifdef old
  177.             if((cp = strchr(line,' ')) == NULLCHAR
  178.             && (cp = strchr(line,'\t')) == NULLCHAR){
  179.                 break;
  180.             }
  181. #endif
  182.             for(cp=line;*cp;cp++) {
  183.                 if(*cp == ' ' || *cp == '\t')
  184.                     break;
  185.             }
  186.         /* if we didn't reach end of line yet, cutoff this arg here */
  187.             if(*cp == '\0')
  188.                 break;
  189.             *cp++ = '\0';
  190.             line = cp;
  191.         }
  192.     }
  193.     if (argc < 1) {         /* empty command line */
  194.         argc = 1;
  195.         argv[0] = "";
  196.     }
  197.   
  198. #ifdef LOCK
  199.     /* Check to see if this is the Command session.
  200.      * If so, check to see if the keyboard is locked
  201.      * Added 12/12/91 WG7J
  202.      * Also, skips this check if it is a command from the AT queue
  203.      * 12/16/93 KO4KS
  204.      */
  205.     if((Curproc->input == Command->input) &&
  206.         strcmp ("AT handler", Curproc->name))
  207.         if(Kblocked) { /*check argv[0] for password!*/
  208.             if(strcmp(argv[0],Kbpasswd)) {
  209.                 tputs("\nKeyboard remains locked\n");
  210.                 return 0;
  211.             }
  212.             Command->ttystate.echo = 1; /* turn character echo back on ! */
  213.             Kblocked=0;   /* correct password, so unlock */
  214.             return 0;
  215.         }
  216. #endif
  217.   
  218.     /* Look up command in table; prefix matches are OK */
  219.     /* Not case sensitive anymore - WG7J */
  220.     for(cmdp = cmds;cmdp->name != NULLCHAR;cmdp++){
  221.         if(strncmpi(argv[0],cmdp->name,strlen(argv[0])) == 0)
  222.             break;
  223.     }
  224.     if(cmdp->name == NULLCHAR) {
  225.         if(cmdp->argc_errmsg != NULLCHAR)
  226.             tprintf("%s\n",cmdp->argc_errmsg);
  227.         return -1;
  228.     } else {
  229.         if(argc < cmdp->argcmin) {
  230.             /* Insufficient arguments */
  231.             tprintf("Usage: %s\n",cmdp->argc_errmsg);
  232.             return -1;
  233.         } else {
  234.             if(cmdp->stksize == 0){
  235.                 return (*cmdp->func)(argc,argv,p);
  236.             } else {
  237.                 /* Make private copy of argv and args,
  238.                  * spawn off subprocess and return.
  239.                  */
  240.                 pargv = (char **)callocw(argc,sizeof(char *));
  241.                 for(i=0;i<argc;i++)
  242.                     pargv[i] = strdup(argv[i]);
  243.                 newproc(cmdp->name,cmdp->stksize,
  244.                 (void (*)__ARGS((int,void*,void*)))cmdp->func,argc,pargv,p,1);
  245.                 return(0);
  246.             }
  247.         }
  248.     }
  249. }
  250.   
  251. /* Call a subcommand based on the first token in an already-parsed line */
  252. int
  253. subcmd(tab,argc,argv,p)
  254. struct cmds tab[];
  255. int argc;
  256. char *argv[];
  257. void *p;
  258. {
  259.     register struct cmds *cmdp;
  260.     char **pargv;
  261.     int found = 0;
  262.     int i;
  263.   
  264.     /* Strip off first token and pass rest of line to subcommand */
  265.     if (argc < 2) {
  266.         if (argc < 1)
  267.             tputs("SUBCMD - Don't know what to do?\n");
  268.         else
  269.             tprintf("\"%s\" - takes at least one argument\n",argv[0]);
  270.         return -1;
  271.     }
  272.     argc--;
  273.     argv++;
  274.     for(cmdp = tab;cmdp->name != NULLCHAR;cmdp++){
  275.     /* Not case sensitive anymore - WG7J */
  276.         if(strncmpi(argv[0],cmdp->name,strlen(argv[0])) == 0){
  277.             found = 1;
  278.             break;
  279.         }
  280.     }
  281.     if(!found){
  282.         char buf[77];
  283.         memset(buf,' ',sizeof(buf));
  284.         buf[75] = '\n';
  285.         buf[76] = '\0';
  286.         tputs("valid subcommands:\n");
  287.         for(i = 0, cmdp = tab;cmdp->name != NULLCHAR; cmdp++, i = (i+1)%5) {
  288.             strncpy(&buf[i*15],cmdp->name,strlen(cmdp->name));
  289.             if(i == 4) {
  290.                 tputs(buf);
  291.                 memset(buf,' ',sizeof(buf));
  292.                 buf[75] = '\n';
  293.                 buf[76] = '\0';
  294.             }
  295.         }
  296.         if(i != 0)
  297.             tputs(buf);
  298.         return -1;
  299.     }
  300.     if(argc < cmdp->argcmin){
  301.         if(cmdp->argc_errmsg != NULLCHAR)
  302.             tprintf("Usage: %s\n",cmdp->argc_errmsg);
  303.         return -1;
  304.     }
  305.     if(cmdp->stksize == 0){
  306.         return (*cmdp->func)(argc,argv,p);
  307.     } else {
  308.         /* Make private copy of argv and args */
  309.         pargv = (char **)callocw(argc,sizeof(char *));
  310.         for(i=0;i<argc;i++)
  311.             pargv[i] = strdup(argv[i]);
  312.         newproc(cmdp->name,cmdp->stksize,
  313.         (void (*)__ARGS((int,void*,void*)))cmdp->func,argc,pargv,p,1);
  314.         return(0);
  315.     }
  316. }
  317.   
  318. /* Subroutine for setting and displaying boolean flags */
  319. int
  320. setbool(var,label,argc,argv)
  321. int *var;
  322. char *label;
  323. int argc;
  324. char *argv[];
  325. {
  326.     struct boolcmd *bc;
  327.   
  328.     if(argc < 2){
  329.         tprintf("%s: %s\n",label,*var ? "on":"off");
  330.         return 1;
  331.     }
  332.     for(bc = Boolcmds;bc->str != NULLCHAR;bc++){
  333.         if(strcmpi(argv[1],bc->str) == 0){
  334.             *var = bc->val;
  335.             return 0;
  336.         }
  337.     }
  338.     tputs("Valid options:");
  339.     for(bc = Boolcmds;bc->str != NULLCHAR;bc++)
  340.         if(tprintf(" %s",bc->str) == EOF)
  341.             return 1;
  342.     tputc('\n');
  343.     return 1;
  344. }
  345.   
  346.   
  347. #ifdef PPP
  348. /* Subroutine for setting and displaying bit values */
  349. int
  350. bit16cmd(bits,mask,label,argc,argv)
  351. int16 *bits;
  352. int16 mask;
  353. char *label;
  354. int argc;
  355. char *argv[];
  356. {
  357.     int doing = (*bits & mask);
  358.     int result = setbool( &doing, label, argc, argv );
  359.   
  360.     if ( !result ) {
  361.         if ( doing )
  362.             *bits |= mask;
  363.         else
  364.             *bits &= ~mask;
  365.     }
  366.     return result;
  367. }
  368. #endif
  369.   
  370. /* Subroutine for setting and displaying long variables */
  371. int
  372. setlong(var,label,argc,argv)
  373. long *var;
  374. char *label;
  375. int argc;
  376. char *argv[];
  377. {
  378.     if(argc < 2){
  379.         tprintf("%s: %ld\n",label,*var);
  380.         return 1;
  381.     } else {
  382.         *var = atol(argv[1]);
  383.         return 0;
  384.     }
  385.   
  386. }
  387. /* Subroutine for setting and displaying short variables */
  388. int
  389. setshort(var,label,argc,argv)
  390. unsigned short *var;
  391. char *label;
  392. int argc;
  393. char *argv[];
  394. {
  395.     if(argc < 2){
  396.         tprintf("%s: %u\n",label,*var);
  397.         return 1;
  398.     } else {
  399.         *var = atoi(argv[1]);
  400.         return 0;
  401.     }
  402. }
  403. /* Subroutine for setting and displaying integer variables */
  404. int
  405. setint(var,label,argc,argv)
  406. int *var;
  407. char *label;
  408. int argc;
  409. char *argv[];
  410. {
  411.     if(argc < 2){
  412.         tprintf("%s: %i\n",label,*var);
  413.         return 1;
  414.     } else {
  415.         *var = atoi(argv[1]);
  416.         return 0;
  417.     }
  418.   
  419. }
  420.   
  421. /* Subroutine for setting and displaying unsigned integer variables */
  422. int
  423. setuns(var,label,argc,argv)
  424. unsigned *var;
  425. char *label;
  426. int argc;
  427. char *argv[];
  428. {
  429.     if(argc < 2){
  430.         tprintf("%s: %u\n",label,*var);
  431.         return 1;
  432.     } else {
  433.         *var = atoi(argv[1]);
  434.         return 0;
  435.     }
  436. }
  437.   
  438. /* Subroutine for setting and displaying int variables (with range check) */
  439. int
  440. setintrc(var, label, argc, argv, minval, maxval)
  441. int16 *var;
  442. char *label;
  443. int argc;
  444. char *argv[];
  445. int minval;
  446. int16 maxval;
  447. {
  448.     int tmp;
  449.   
  450.     if (argc < 2)
  451.         tprintf("%s: %u\n", label, *var);
  452.     else {
  453.         tmp = atoi(argv[1]);
  454.         if (isalpha(*argv[1]) || tmp < minval || tmp > maxval) {
  455.             tprintf("%s must be %i..%i\n", label, minval, maxval);
  456.             return 1;
  457.         }
  458.         *var = (int16)tmp;
  459.     }
  460.     return 0;
  461. }
  462.   
  463. /* Set flags on ax.25 interfaces - WG7J */
  464.   
  465. int setflag(int argc,char *ifname,long flag,char *cmd) {
  466.     struct iface *ifp;
  467.     struct boolcmd *bc;
  468.   
  469.     if(argc == 1) {
  470.         for(ifp = Ifaces;ifp != NULLIF;ifp = ifp->next)
  471.             if(ifp->flags & flag)
  472.                 tprintf("%s\n",ifp->name);
  473.     } else {
  474.         if((ifp = if_lookup(ifname)) == NULLIF){
  475.             tprintf(Badinterface,ifname);
  476.             return 1;
  477.         }
  478.         /*
  479.         if(ifp->type != CL_AX25) {
  480.             tputs("not an AX.25 interface\n");
  481.             return 1;
  482.         }
  483.         */
  484.         if(argc == 2) {
  485.             /* Show the value of the flag */
  486.             if(ifp->flags & flag)
  487.                 tputs("On\n");
  488.             else
  489.                 tputs("Off\n");
  490.         } else {
  491.             for(bc = Boolcmds;bc->str != NULLCHAR;bc++)
  492.                 if(strcmpi(cmd,bc->str) == 0){
  493.                     if(bc->val)
  494.                         ifp->flags |= flag;
  495.                     else
  496.                         ifp->flags &= ~flag;
  497.                     return 0;
  498.                 }
  499.             /* Invalid option ! */
  500.             tputs("Valid options:");
  501.             for(bc = Boolcmds;bc->str != NULLCHAR;bc++)
  502.                 if(tprintf(" %s",bc->str) == EOF)
  503.                     return 1;
  504.             tputc('\n');
  505.         }
  506.     }
  507.     return 0;
  508. }
  509.   
  510.   
  511.